//
//  Selector+ZLExtensions.swift
//  ZLKit
//
//  Created by itzhaolei on 2021/9/9.
//

import Foundation

open class Action {
    
    weak var target: NSObject?
    var action: Selector
    
    /// 初始化事件对象
    ///
    /// 内部做了弱引用解引用，放心传递
    /// - Parameters:
    ///   - target: 调用者
    ///   - action: 事件
    public init(target: NSObject?, action: Selector) {
        self.target = target
        self.action = action
    }
    
    /// 响应与当前对象绑定的函数，响应时支持携带最多2个参数
    /// - Parameters:
    ///   - obj1: 调用时传入参数1
    ///   - obj2: 调用时传入参数2
    public func perform(_ obj1: NSObject? = nil, _ obj2: NSObject? = nil) {
        guard let safeTarget = target else { return }
        guard safeTarget.responds(to: action) else { return }
        if let safe1 = obj1, let safe2 = obj2 {
            safeTarget.perform(action, with: safe1, with: safe2)
            return
        }
        if let safe1 = obj1 {
            safeTarget.perform(action, with: safe1)
            return
        }
        safeTarget.perform(action)
    }
    
    /// 后台调用事件，并传入不固定的参数
    /// - Parameters:
    ///   - inBackground: 事件
    ///   - arg: 调用时传入参数[任意对象类型]
    public func performInBackground(arg: [NSObject]?) {
        guard let safeTarget = target else { return }
        guard safeTarget.responds(to: action) else { return }
        safeTarget.performSelector(inBackground: action, with: arg)
    }
    
    
    /// 调用事件
    /// - Parameters:
    ///   - arg: 调用时传入参数[任意类型]
    ///   - delay: 延迟调用时间
    ///   - modes: 指定执行的RunLoop模式
    public func perform(arg: [NSObject]?, delay: TimeInterval, modes: [RunLoop.Mode] = []) {
        guard let safeTarget = target else { return }
        guard safeTarget.responds(to: action) else { return }
        safeTarget.perform(action, with: arg, afterDelay: delay, inModes: modes)
    }
    
    
    /// 调用事件
    /// - Parameters:
    ///   - onThread: 在哪个线程执行
    ///   - arg: 调用时传入参数[任意类型]
    ///   - waitUntilDone: 是否等到完成
    ///   - modes: 指定执行的RunLoop模式
    public func perform(onThread: Thread = .main, arg: [NSObject]?, waitUntilDone: Bool, modes: [String]? = nil) {
        guard let safeTarget = target else { return }
        guard safeTarget.responds(to: action) else { return }
        if onThread == .main {
            safeTarget.performSelector(onMainThread: action, with: arg, waitUntilDone: waitUntilDone, modes: modes)
            return
        }
        safeTarget.perform(action, on: onThread, with: arg, waitUntilDone: waitUntilDone, modes: modes)
    }
    
}

